#include <iostream>
#include <cstdlib>
#include <cassert>
#include <string>
using namespace std;

#include "Graph.h"
#include "Node.h"
#include "Algorithm.h"
#include "test.h"

#define GLOUTON 0
#define BACKTRACK 1
#define NOCHOICE 2
#define NOCHOICE2 3

#define BOUCLE 100
#define TAILLE_MAX 300

void decolore(Graph *g) {
    vector<NodeList *> * adj = g->getAdjacencyList();
    for (lnodelist_it i = adj->begin(); i != adj->end(); ++i) {
        (*i)->front()->setColor(-1);
    }
}

vector<stats> *benchmark(int algo, double p, int k) {
    vector<stats> *tab = new vector<stats > ();

    switch (algo) {
        case GLOUTON:
            for (int i = 0; i < BOUCLE; ++i) {
                //On genere aleatoirement la taille du graphe a chaque tour de boucle (entre 1 et TAILLE_MAX)
                //int n_random = 50 + rand() % TAILLE_MAX;
                int k_s = 0;
                int n_s = 0;
                for (int j = 0; j < 10; j++) {
                    n_s += i + 1;
                    Graph * g = new Graph(i + 1, p);

                    //On récupère le k-max du graph
                    k_s += greedy_algorithm(g);
                    delete(g);
                }
                k_s /= 10;
                n_s /= 10;
                stats s = (stats) malloc(sizeof (*s));
                s->nb_sommets = n_s;
                s->k = k_s;
                s->pourcent = 100; //Glouton rempli le graphe a coup sur

                //Et on la stocke
                tab->push_back(s);
            }
            break;
        case BACKTRACK:
            for (int i = 0; i < BOUCLE; ++i) {

                //On genere aleatoirement la taille du graphe a chaque tour de boucle (entre 1 et TAILLE_MAX)
                //int n_random = 50 + rand() % TAILLE_MAX;
                int n_s = 0;
                int n_m = 0;
                for (int j = 0; j < 10; j++) {
                    int n_random = i + 1;
                    n_s += n_random;
                    Graph * g = new Graph(n_random, p);

                    int n_max = backtracking_algorithm(g, k);
                    n_m += n_max;
                    //On cree la nouvelle statistique

                    delete(g);
                }
                n_s /= 10;
                n_m /= 10;
                stats s = (stats) malloc(sizeof (*s));
                s->nb_sommets = n_s;
                s->k = k;
                s->pourcent = n_m * 100 / n_s;

                //Et on la stocke
                tab->push_back(s);
            }
            break;
        case NOCHOICE:
            for (int i = 0; i < BOUCLE; ++i) {

                //On genere aleatoirement la taille du graphe a chaque tour de boucle (entre 1 et TAILLE_MAX)
                //int n_random = 50 + rand() % TAILLE_MAX;
                int n_s = 0;
                int n_m = 0;
                for (int j = 0; j < 10; j++) {
                    int n_random = i + 1;
                    n_s += n_random;
                    Graph * g = new Graph(n_random, p);
                    int n_max = nochoice_algorithm(g, k);
                    n_m += n_max;

                    //On cree la nouvelle statistique

                    delete(g);
                }
                n_s /= 10;
                n_m /= 10;
                stats s = (stats) malloc(sizeof (*s));
                s->nb_sommets = n_s;
                s->k = k;
                s->pourcent = n_m * 100 / n_s;

                //Et on la stocke
                tab->push_back(s);
            }
            break;
        case NOCHOICE2:
            for (int i = 0; i < BOUCLE; ++i) {

                //On genere aleatoirement la taille du graphe a chaque tour de boucle (entre 1 et TAILLE_MAX)
                //int n_random = 50 + rand() % TAILLE_MAX;
                int n_s = 0;
                int n_m = 0;
                for (int j = 0; j < 10; j++) {
                    int n_random = i + 1;
                    n_s += n_random;
                    Graph * g = new Graph(n_random, p);
                    int n_max = nochoice_algorithm_optimized2(g, k);
                    n_m += n_max;

                    //On cree la nouvelle statistique

                    delete(g);
                }
                n_s /= 10;
                n_m /= 10;
                stats s = (stats) malloc(sizeof (*s));
                s->nb_sommets = n_s;
                s->k = k;
                s->pourcent = n_m * 100 / n_s;

                //Et on la stocke
                tab->push_back(s);
            }
            break;
        default:
            cout << "Mauvais algo en parametre" << endl;
            exit(1);
            break;
    }
    return tab;
}

void saveOnTestFile(string test_file_path, vector<stats> *s, int glouton) {
    ofstream test_file(test_file_path.c_str());

    if (!glouton)
        for (int i = 0; i < s->size(); i++)
            test_file << s->at(i)->nb_sommets << " " << s->at(i)->pourcent << endl;
    else
        for (int i = 0; i < s->size(); i++)
            test_file << s->at(i)->nb_sommets << " " << s->at(i)->k << endl;

}

void launch_bench(double p) {

  /* vector<stats> *backtrack2 = benchmark(BACKTRACK, p, 2);
    saveOnTestFile("test/backtrack2.txt", backtrack2, 0);
    vector<stats> *backtrack3 = benchmark(BACKTRACK, p, 3);
    saveOnTestFile("test/backtrack3.txt", backtrack3, 0);
    vector<stats> *backtrack4 = benchmark(BACKTRACK, p, 4);
    saveOnTestFile("test/backtrack4.txt", backtrack4, 0);
    vector<stats> *backtrack5 = benchmark(BACKTRACK, p, 5);
    saveOnTestFile("test/backtrack5.txt", backtrack5, 0);
    vector<stats> *backtrack6 = benchmark(BACKTRACK, p, 6);
    saveOnTestFile("test/backtrack6.txt", backtrack6, 0);
    vector<stats> *backtrack7 = benchmark(BACKTRACK, p, 7);
    saveOnTestFile("test/backtrack7.txt", backtrack7, 0);

    cout << "Benchmark Backtrack terminé" << endl;*/

    vector<stats> *nochoice2 = benchmark(NOCHOICE, p, 2);
    saveOnTestFile("test/nochoice2.txt", nochoice2, 0);
    vector<stats> *nochoice3 = benchmark(NOCHOICE, p, 3);
    saveOnTestFile("test/nochoice3.txt", nochoice3, 0);
    vector<stats> *nochoice4 = benchmark(NOCHOICE, p, 4);
    saveOnTestFile("test/nochoice4.txt", nochoice4, 0);
    vector<stats> *nochoice5 = benchmark(NOCHOICE, p, 5);
    saveOnTestFile("test/nochoice5.txt", nochoice5, 0);
    vector<stats> *nochoice6 = benchmark(NOCHOICE, p, 6);
    saveOnTestFile("test/nochoice6.txt", nochoice6, 0);
    vector<stats> *nochoice7 = benchmark(NOCHOICE, p, 7);
    saveOnTestFile("test/nochoice7.txt", nochoice7, 0);

    cout << "Benchmark Nochoice terminé" << endl;

    vector<stats> *nochoice_2 = benchmark(NOCHOICE2, p, 2);
    saveOnTestFile("test/nochoice_2.txt", nochoice_2, 0);
    vector<stats> *nochoice_3 = benchmark(NOCHOICE2, p, 3);
    saveOnTestFile("test/nochoice_3.txt", nochoice_3, 0);
    vector<stats> *nochoice_4 = benchmark(NOCHOICE2, p, 4);
    saveOnTestFile("test/nochoice_4.txt", nochoice_4, 0);
    vector<stats> *nochoice_5 = benchmark(NOCHOICE2, p, 5);
    saveOnTestFile("test/nochoice_5.txt", nochoice_5, 0);
    vector<stats> *nochoice_6 = benchmark(NOCHOICE2, p, 6);
    saveOnTestFile("test/nochoice_6.txt", nochoice_6, 0);
    vector<stats> *nochoice_7 = benchmark(NOCHOICE2, p, 7);
    saveOnTestFile("test/nochoice_7.txt", nochoice_7, 0);

    cout << "Benchmark Nochoice2 terminé" << endl;

    /*vector<stats> *glouton2 = benchmark(GLOUTON, 0.2, 0);
    saveOnTestFile("test/glouton2.txt", glouton2, 1);

    vector<stats> *glouton5 = benchmark(GLOUTON, 0.5, 0);
    saveOnTestFile("test/glouton5.txt", glouton5, 1);

    vector<stats> *glouton8 = benchmark(GLOUTON, 0.8, 0);
    saveOnTestFile("test/glouton8.txt", glouton8, 1);

    cout << "Benchmark glouton terminé" << endl;*/
    }
